package com.etc.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.etc.entity.Audit;
import com.etc.entity.Contents;
import com.etc.entity.Files;
import com.etc.service.AuditService;
import com.etc.service.ContentsService;
import com.etc.service.FileService;
import com.etc.util.CommenMassage;
import com.etc.util.CopyDocuments;
import com.etc.util.DeleteUtil;
import com.etc.util.TestCopyFiles2;

@Controller
public class DirectoryController {
	private String destDir = "D:\\apache-tomcat-8.5.13-windows-x64\\apache-tomcat-8.5.13\\webapps";

	@Autowired
	private FileService fileService;

	@Autowired
	private ContentsService contentsService;

	@Autowired
	private CommenMassage commenMassage;

	@Autowired
	private TestCopyFiles2 testCopyFiles2;

	@Autowired
	private CopyDocuments copyDocuments;

	@Autowired
	private DeleteUtil deleteUtil;

	@Autowired
	private AuditService auditService;

	/**
	 * 新建文件夹的接口
	 * 
	 * @param secondId
	 *            上一级目录的id
	 * @param userId
	 *            用户id
	 * @param contentsName
	 *            文件夹名
	 * @return CommenMassage工具类
	 */
	@RequestMapping(value = "addContents", method = RequestMethod.GET)
	@ResponseBody
	public CommenMassage addContents(Integer secondId, Integer userId, String contentsName) {

		// 查询文件夹是否存在
		Contents contents2 = contentsService.selectBySecondIdAndContentsName(secondId, contentsName);
		if (contents2 != null) {
			commenMassage.setMsg("文件夹名重复");
		} else {
			// 创建Contents类并赋值
			Contents contents = new Contents(userId, contentsName, secondId, new Date().toLocaleString());

			// 存储
			boolean flag = contentsService.addContents(contents);

			// 如果flag为真，返回新建成功，否则返回新建失败
			if (flag) {
				commenMassage.setMsg("新建成功");
			} else {
				commenMassage.setMsg("新建失败");
			}
		}

		return commenMassage;
	}

	/**
	 * 显示目录和文件的接口
	 * 
	 * @param secondId
	 *            上一级目录的id
	 * @param userId
	 *            用户id
	 * @param model
	 *            Model接口，用来存放数据
	 * @return files.jsp
	 */
	@RequestMapping(value = "directory", method = RequestMethod.GET)
	public String getFile(Integer secondId, Integer userId, Model model) {

		// 得到所有文件
		List<Files> fileList = fileService.getFileBySecondId(secondId, userId);

		// 得到所有目录
		List<Contents> contentsList = contentsService.getContentsBySecondId(secondId, userId);

		model.addAttribute("contents", contentsList);

		model.addAttribute("files", fileList);

		return "files";
	}

	/**
	 * 显示目录和文件的接口(模糊插询)
	 * 
	 * @param secondId
	 *            上一级目录的id
	 * @param userId
	 *            用户id
	 * @param model
	 *            Model接口，用来存放数据
	 * @return files.jsp
	 */
	@RequestMapping(value = "seach", method = RequestMethod.GET)
	public String getFileLike(Integer userId, Model model,
			@RequestParam(value = "content", defaultValue = "") String content) {

		if (content != "") {
			// 得到所有文件
			List<Files> fileList = fileService.getFileByLike(userId, content);

			// 得到所有目录
			List<Contents> contentsList = contentsService.getContentsByLike(userId, content);

			model.addAttribute("contents", contentsList);

			model.addAttribute("files", fileList);
			return "files";
		} else {
			return getFile(0, userId, model);
		}

	}

	/**
	 * 返回上一级的接口
	 * 
	 * @param secondId
	 *            上一级目录的id
	 * @param userId
	 *            用户id
	 * @param model
	 *            Model接口，调用其他控制器接口时使用
	 * @return files.jsp
	 */
	@RequestMapping(value = "getSecondId", method = RequestMethod.GET)
	public String getSecondIdBySecondId(@RequestParam(value = "secondId") Integer secondId,
			@RequestParam(value = "userId") Integer userId, Model model) {

		Integer parentSecondId = contentsService.getSecondIdBySecondId(secondId);

		// HttpHeaders headers = new HttpHeaders();
		//
		// headers.setLocation(ucBuilder.path("/directory?secondId=" + parentSecondId +
		// "&userId=" + userId)
		// .buildAndExpand().toUri());

		// String file = getFile(parentSecondId, userId, model);

		// return "forward:directory/?secondId="+parentSecondId+"&userId="+userId;
		return getFile(parentSecondId, userId, model);
	}

	/**
	 * 重命名接口
	 * 
	 * @param oldname
	 *            旧文件或目录名
	 * @param newfilename
	 *            新文件或目录名
	 * @param filetype
	 *            文件类型
	 * @param secondId
	 *            上一级目录id
	 * @return commenMassage工具类，提示成功或失败
	 */
	@RequestMapping(value = "renameFile", method = RequestMethod.POST)
	@ResponseBody
	public CommenMassage reName(@RequestParam(value = "oldname") String oldname,
			@RequestParam(value = "newname") String newfilename,
			@RequestParam(value = "filetype", defaultValue = "0") Integer filetype,
			@RequestParam(value = "secondId") Integer secondId) {

		// 如果filetype不为空则调用文件的重命名方法,如果为空则调用目录的重命名方法
		if (filetype > 0) {
			// 查询文件是否存在
			Files file = fileService.selectByFnameAndSid(secondId, newfilename);
			if (file != null) {
				commenMassage.setMsg("文件名重复");
			} else {
				boolean flag = fileService.reName(oldname, newfilename, secondId);
				// 如果成功则提示重命名成功，失败则提示重命名失败
				if (flag) {
					commenMassage.setMsg("重命名成功");
				} else {
					commenMassage.setMsg("重命名失败");
				}
			}

		} else {
			// 查询目录是否存在
			Contents contents2 = contentsService.selectBySecondIdAndContentsName(secondId, newfilename);
			if (contents2 != null) {
				commenMassage.setMsg("文件夹名重复");
			} else {
				boolean flag = contentsService.reName(oldname, newfilename, secondId);
				if (flag) {
					commenMassage.setMsg("重命名成功");
				} else {
					commenMassage.setMsg("重命名失败");
				}
			}
		}
		return commenMassage;
	}

	/**
	 * 删除目录或文件
	 * 
	 * @param name
	 *            目录或文件名
	 * @param filetype
	 *            类型，用于判断是否是目录
	 * @param secondId
	 *            上一级目录id
	 * @return CommenMassage提示信息
	 */
	@RequestMapping(value = "deleteFile", method = RequestMethod.POST)
	@ResponseBody
	public CommenMassage reName(@RequestParam(value = "name") String[] name,
			@RequestParam(value = "filetype") Integer[] filetype, @RequestParam(value = "secondId") Integer secondId,
			@RequestParam(value = "userId") Integer userId) {

		// 设置flag初始值
		boolean flag = false;
		// 遍历filetype如果值为0则调用目录的方法
		for (int i = 0; i < filetype.length; i++) {
			if (filetype[i] == 0) {
				Contents contents = contentsService.selectBySecondIdAndContentsName(secondId, name[i]);
				// 删除目录
				flag = contentsService.deleteContents(secondId, name[i]);
				if (flag) {
					// 删除目录下的目录或文件
					flag = deleteUtil.deleteContents(contents.getContentsid(), userId);
				}
			} else {
				flag = fileService.deleteFiles(secondId, name[i]);
			}
		}
		if (flag) {
			commenMassage.setMsg("删除成功");
		} else {
			commenMassage.setMsg("删除失败");
		}
		return commenMassage;
	}

	/**
	 * 删除审核文件
	 * 
	 * @param name
	 *            审核文件名
	 * @param userId
	 *            用户id
	 * @return CommenMassage提示信息
	 */
	@RequestMapping(value = "deletAudit", method = RequestMethod.POST)
	@ResponseBody
	public CommenMassage delAudit(@RequestParam(value = "name") String[] name,
			@RequestParam(value = "userId") Integer userId) {
		for (int i = 0; i < name.length; i++) {
			Audit audit = auditService.selectByName(userId, name[i]);
			boolean flag = auditService.deleteByPrimaryKey(audit.getFileid());
			if (flag) {
				commenMassage.setMsg("删除成功");
			} else {
				commenMassage.setMsg("删除失败");
			}
		}
		return commenMassage;
	}

	/**
	 * 根据用户id和文件类型查询所有文件
	 * 
	 * @param fileType
	 *            文件类型
	 * @param userId
	 *            用户id
	 * @param model
	 *            存放数据
	 * @return
	 */
	@RequestMapping(value = "getFile", method = RequestMethod.GET)
	public String getFileByFileType(@RequestParam(value = "fileType") Integer fileType,
			@RequestParam(value = "userId") Integer userId, Model model) {

		List<Files> fileList = fileService.selectByUserIdAndFileType(userId, fileType);
		model.addAttribute("files", fileList);
		return "files";
	}

	/**
	 * 根据用户id和文件类型查询所有文件
	 * 
	 * @param fileType
	 *            文件类型
	 * @param userId
	 *            用户id
	 * @param model
	 *            存放数据
	 * @return
	 */
	@RequestMapping(value = "myAudit", method = RequestMethod.GET)
	public String getAudit(@RequestParam(value = "userId") Integer userId, Model model) {

		List<Audit> list = auditService.getMyAudit(userId);
		model.addAttribute("auditFiles", list);
		return "audit";
	}

	/**
	 * 文件的复制粘贴 目录的复制粘贴
	 * 
	 * @param fromsecondId
	 *            源文件父目录id
	 * @param userId
	 *            用户id
	 * @param type
	 *            文件类型
	 * @param fromcontentsName
	 *            源文件目录名字
	 * @param tosecondId
	 *            目标位置的父目录id
	 * @param request
	 *            请求
	 * @throws Exception
	 *             文件异常
	 */
	@RequestMapping(value = "copy", method = RequestMethod.GET)
	@ResponseBody
	public void getSecondIdBySecondId(Integer fromsecondId, Integer userId, Integer[] type, String[] fromcontentsName,
			Integer tosecondId, HttpServletRequest request) throws Exception {

		for (int i = 0; i < type.length; i++) {

			// 根据复制目录父目录id查询目录
			if (type[i] > 0) {
				// 复制文件
				copyDocuments.copyDocuments(fromsecondId, tosecondId, fromcontentsName[i]);
			} else {
				// 复制目录
				Integer secondId = contentsService.selectBySecondIdAndContentsName(fromsecondId, fromcontentsName[i])
						.getContentsid();
				testCopyFiles2.CopyFiles(userId, secondId, tosecondId, fromcontentsName[i]);
			}
		}

	}

	/**
	 * 多文件打包下载
	 * 
	 * @param fileName
	 *            文件名
	 * @param secondId
	 *            上一级目录id
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping(value = "downloadFile", method = RequestMethod.GET)
	@ResponseBody
	public HttpServletResponse downloadFileZip(@RequestParam(value = "fileName") String[] fileName,
			@RequestParam(value = "secondId") Integer secondId, HttpServletResponse response) throws IOException {
		try {
			String zipFilename = "D:/" + fileName[0] + ".zip";
			File file = new File(zipFilename);
			file.createNewFile();
			if (!file.exists()) {
				file.createNewFile();
			}
			// 清除首部的空白行
			response.reset();
			// response.getWriter()
			// 创建文件输出流
			FileOutputStream fous = new FileOutputStream(file);
			ZipOutputStream zipOut = new ZipOutputStream(fous);
			zipFile(fileName, zipOut, secondId);
			zipOut.close();
			fous.close();
			return downloadZip(file, response);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return response;
	}

	/**
	 * 把接受的全部文件打成压缩包
	 * 
	 * @param List<File>;
	 * @param org.apache.tools.zip.ZipOutputStream
	 */
	public void zipFile(String[] files, ZipOutputStream outputStream, Integer secondId) {
		int size = files.length;
		for (int i = 0; i < size; i++) {
			String filepath = fileService.selectByFnameAndSid(secondId, files[i]).getFilepath();
			String[] strings = filepath.split("/");
			String realpath = destDir + "\\" + strings[3] + "\\" + strings[4];
			File file = new File(realpath);
			zipFile(file, outputStream);
		}
	}

	/**
	 * 根据输入的文件与输出流对文件进行打包
	 * 
	 * @param Files
	 * @param org.apache.tools.zip.ZipOutputStream
	 */
	public void zipFile(File inputFile, ZipOutputStream ouputStream) {
		try {
			if (inputFile.exists()) {
				if (inputFile.isFile()) {
					FileInputStream IN = new FileInputStream(inputFile);
					BufferedInputStream bins = new BufferedInputStream(IN, 512);
					ZipEntry entry = new ZipEntry(inputFile.getName());
					ouputStream.putNextEntry(entry);
					// 向压缩文件中输出数据
					int nNumber;
					byte[] buffer = new byte[512];
					while ((nNumber = bins.read(buffer)) != -1) {
						ouputStream.write(buffer, 0, nNumber);
					}
					// 关闭创建的流对象
					bins.close();
					IN.close();
				} else {
					try {
						File[] files = inputFile.listFiles();
						for (int i = 0; i < files.length; i++) {
							zipFile(files[i], ouputStream);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@ResponseBody
	public HttpServletResponse downloadZip(File file, HttpServletResponse response) {
		InputStream fis = null;
		OutputStream toClient = null;
		if (file.exists() == false) {
		} else {
			try {
				// 以流的形式下载文件。
				fis = new BufferedInputStream(new FileInputStream(file.getPath()));
				byte[] buffer = new byte[fis.available()];
				fis.read(buffer);

				// 清空response
				response.reset();

				toClient = new BufferedOutputStream(response.getOutputStream());
				response.setContentType("application/octet-stream");

				// 如果输出的是中文名的文件，在此处就要用URLEncoder.encode方法进行处理
				// response.setHeader("Content-Disposition",
				// "attachment;filename=" + new String(file.getName().getBytes("GB2312"),
				// "ISO8859-1"));
				response.setHeader("Content-Disposition",
						"attachment;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
				toClient.write(buffer);
				toClient.flush();
			} catch (Exception ex) {
				ex.printStackTrace();
			} finally {
				try {
					File f = new File(file.getPath());
					f.delete();
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (toClient != null) {
					try {
						toClient.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if (fis != null) {
					try {
						fis.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		return response;
	}

}
